#include <iostream>
#include <fstream>
#include "B_Form.h"
#include <cmath>
#include <algorithm>
#include <vector>
#include <jsoncpp/json/json.h>
using namespace std;
class Fun : public Function
{
public:
    double operator()(double _x)
    {
        double y;
        y = 1/(1 + _x*_x);
        return y;
    }
    double diff(double _x) 
    {
        double y;
        y = -2.0*_x/pow(1.0 + _x*_x, 2);
        return y;  
    }
    double diff2(double _x)
    {
        double y;
        y = 2.0*(3.0*_x*_x - 1.0)/pow(1.0 + _x*_x, 3);
        return y;  
    }
};

int main()
{
    Json::Reader reader;
    Json::Value root;
    ofstream fout, fout1, fout2;
 
    ifstream in("./date/input/C.json", ios::binary);
    if (!in.is_open())
    {
        cout << "error: cannot open file." << endl;
	return -1;
    }

    vector<double> point1, point2, output_point;
    Fun f;

    if (reader.parse(in, root))
	{
        for (int i = 0; i < root["point1"].size(); i++)
	    {
	        double temp_n = root["point1"][i].asDouble();
	        point1.push_back(temp_n);
	    }
        for (int i = 0; i < root["point2"].size(); i++)
	    {
	        double temp_n = root["point2"][i].asDouble();
	        point2.push_back(temp_n);
	    }
        for (int i = 0; i < root["output_point"].size(); i++)
	    {
	        double temp_n = root["output_point"][i].asDouble();
	        output_point.push_back(temp_n);
	    }
    }

    fout.open("probC_points.txt");
    fout1.open("probD_error.txt");
    fout2.open("probD_errorpoints.txt");

/**
 * cubic
*/
    Bspline B1(f, point1, 1, 3);
    B1.cal();
    fout << "Cubic spline " << endl;
    fout2 << "Error function of cubic spline " << endl;
    for (int i = 0; i < 1000; i++)
	{
        fout << B1(point1[0] + i*0.01) << ", ";
        fout2 << fabs(B1(point1[0] + i*0.01) - f(point1[0] + i*0.01)) << ", ";
	}
    fout << B1(point1[point1.size()-1]) <<endl<<endl;
    fout2 << fabs(B1(point1[point1.size()-1]) - f(point1[point1.size()-1])) <<endl;

/**
 * quadatic
*/
    Bspline B2(f, point2, 3, 3);
    B2.cal();
    fout << "quadatic spline" << endl;
    fout2 << "Error function of quadatic spline " << endl;
    for (int i = 0; i < 900; i++)
	{
        fout << B2(point2[0] + i*0.01) << ", ";
        fout2 << fabs(B2(point2[0] + i*0.01) - f(point2[0] + i*0.01)) << ", ";
	}
    fout << B2(point2[point2.size()-1]) <<endl<<endl;
    fout2 << fabs(B2(point2[point2.size()-1]) - f(point2[point2.size()-1])) <<endl;



    vector<double> err_1, err_2;
    fout1 << "Error values of cubic spline " << endl;
    for (int i = 0; i < output_point.size() - 1; i++)
	{
	        fout1 << fabs(B1(output_point[i]) - f(output_point[i])) << ", ";
	}
    fout1 << fabs(B1(output_point[output_point.size() - 1]) - f(output_point[output_point.size() - 1])) << endl;
    fout1 << "Error values of quadatic spline" << endl;
    for (int i = 0; i < output_point.size() - 1; i++)
	{
	        fout1 << fabs(B2(output_point[i]) - f(output_point[i])) << ", ";
	}
    fout1 << fabs(B2(output_point[output_point.size() - 1]) - f(output_point[output_point.size() - 1])) << endl;
    
    fout.close();
    fout1.close();
    fout2.close();

    return 0;
}

